﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace ArchiveSearch
{
    public delegate void DebugConsole(string message);
    public delegate void PostAdder(ChanSharp.Post post);
    public delegate void PictureAdder(Bitmap item);

    public partial class SearchResults : Form
    {
        public FilterSet filterSet;
        public DebugConsole handler;
        public PostAdder postAdder;
        public PictureAdder pictureAdder;
        public static string yotsubabluenew;
        CustomDrawListBox customListView1;

        static SearchResults()
        {
            yotsubabluenew = System.IO.File.ReadAllText("yotsubabluenew.css");
        }

        public SearchResults(FilterSet filterSet)
        {
            InitializeComponent();

            this.filterSet = filterSet;

            handler = DebugConsoleWrite;
            postAdder = AddPost;
            pictureAdder = AddPicture;

            customListView1 = new CustomDrawListBox();

            this.customListView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                | System.Windows.Forms.AnchorStyles.Left)
                | System.Windows.Forms.AnchorStyles.Right)));
            this.customListView1.Location = new System.Drawing.Point(4, 4);
            //this.listView1.Name = "listView1";
            this.customListView1.Size = new System.Drawing.Size(489, 288);
            //this.customListView1.TabIndex = 0;
            //this.customListView1.UseCompatibleStateImageBehavior = false;
            //this.customListView1.View = System.Windows.Forms.View.Details;

            //listView1.LargeImageList = new ImageList();
        }

        Thread archT;
        Archive arch;

        Thread tpfT;
        ThreadPostFinder tpf;

        public void CollectResults()
        {
            StartLoadingIconAnim();

            arch = new Archive(handler);
            archT = new Thread(arch.Start);
            archT.Start();

            new Thread(new ThreadStart(delegate
                {
                    while (archT.IsAlive) { Thread.Sleep(10); }
                    tpf = new ThreadPostFinder(handler, postAdder, arch.Threads, filterSet);
                    tpfT = new Thread(tpf.Start);
                    tpfT.SetApartmentState(ApartmentState.STA);
                    tpfT.Start();
                })).Start();
        }

        public void DebugConsoleWrite(string text)
        {
            if (this.textBoxDebug.InvokeRequired)
            {
                DebugConsole d = new DebugConsole(DebugConsoleWrite);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.textBoxDebug.AppendText(text);
            }
        }

        public void AddPost(ChanSharp.Post post)
        {
            DebugConsoleWrite("Found one! " + post + "\r\n");

            string css = "<style type=\"text/css\">\n" + yotsubabluenew + "\n</style>";

            post.RemoveSideArrows();

            string page = "<html>" + css + "\n\n" + post.RawHTML + "</html>";

            WebBrowser wb = new WebBrowser();
            wb.Width = customListView1.Width - 10;
            wb.Height = 255;
            wb.Navigate("about:blank");
            wb.Document.Write(page);

            Bitmap bmp = TakeSnapshot(post, wb);
            bmp.Save("bullshit.png", ImageFormat.Png);
            AddPicture(bmp);
        }

        private void AddPicture(Bitmap bmp)
        {
            if (this.textBoxDebug.InvokeRequired)
            {
                PictureAdder p = new PictureAdder(AddPicture);
                this.Invoke(p, new object[] { bmp });
            }
            else
            {
                //listView1.LargeImageList.Images.Add(bmp);
                //ListViewItem picture = new ListViewItem("", listView1.LargeImageList.Images.Count - 1);
                //listView1.Items.Add(picture);
                customListView1.Items.Add(bmp);
            }
        }

        public Bitmap TakeSnapshot(ChanSharp.Post p, WebBrowser wb)
        {
            try
            {
                Bitmap bmp = new Bitmap(wb.Width, wb.Height);

                Rectangle rec = new Rectangle(0, 0, wb.Width - 17, //cut out the scrollbar
                    wb.Height);

                wb.DrawToBitmap(bmp, rec);

                //TODO: vscroll detection

                return bmp;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Snapshot Error for post " + p, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
        }

        private void StartLoadingIconAnim()
        {
            new Thread(new ThreadStart(delegate
                {
                    int i = 0;
                    while (true)
                    {
                        switch (i)
                        {
                            case 0:
                                pictureBoxLoading.Image = Properties.Resources.p0;
                                break;
                            case 1:
                                pictureBoxLoading.Image = Properties.Resources.p1;
                                break;
                            case 2:
                                pictureBoxLoading.Image = Properties.Resources.p2;
                                break;
                            case 3:
                                pictureBoxLoading.Image = Properties.Resources.p3;
                                break;
                            case 4:
                                pictureBoxLoading.Image = Properties.Resources.p4;
                                break;
                            case 5:
                                pictureBoxLoading.Image = Properties.Resources.p5;
                                break;
                            default:
                                throw new Exception("Images???");
                        }
                        Thread.Sleep(500);
                        i = (i + 1) % 6;
                    }
                })).Start();
        }

        private void SearchResults_FormClosing(object sender, FormClosingEventArgs e)
        {
            arch.Abort();
            archT.Abort();
            tpf.Abort();
            tpfT.Abort();
        }

        private void splitContainer1_Paint(object sender, PaintEventArgs e)
        {
            var control = sender as SplitContainer;
            //paint the three dots'
            Point[] points = new Point[3];
            var w = control.Width;
            var h = control.Height;
            var d = control.SplitterDistance;
            var sW = control.SplitterWidth;

            //calculate the position of the points'
            if (control.Orientation == Orientation.Horizontal)
            {
                points[0] = new Point((w / 2), d + (sW / 2));
                points[1] = new Point(points[0].X - 10, points[0].Y);
                points[2] = new Point(points[0].X + 10, points[0].Y);
            }
            else
            {
                points[0] = new Point(d + (sW / 2), (h / 2));
                points[1] = new Point(points[0].X, points[0].Y - 10);
                points[2] = new Point(points[0].X, points[0].Y + 10);
            }

            foreach (Point p in points)
            {
                p.Offset(-2, -2);
                e.Graphics.FillEllipse(SystemBrushes.ControlDark,
                    new Rectangle(p, new Size(3, 3)));

                p.Offset(1, 1);
                e.Graphics.FillEllipse(SystemBrushes.ControlLight,
                    new Rectangle(p, new Size(3, 3)));
            }
        }
    }

    public class CustomDrawListBox : ListBox
    {
        public CustomDrawListBox()
        {
            this.DrawMode = DrawMode.OwnerDrawVariable; // We're using custom drawing.
            this.ItemHeight = 255; // Set the item height to 40.
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            // Make sure we're not trying to draw something that isn't there.
            if (e.Index >= this.Items.Count || e.Index <= -1)
                return;

            // Get the item object.
            object item = this.Items[e.Index];
            if (item == null)
                return;

            // Draw the background color depending on 
            // if the item is selected or not.
            if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
            {
                // The item is selected.
                // We want a blue background color.
                e.Graphics.FillRectangle(new SolidBrush(Color.Blue), e.Bounds);
            }
            else
            {
                // The item is NOT selected.
                // We want a white background color.
                e.Graphics.FillRectangle(new SolidBrush(Color.White), e.Bounds);
            }

            // Draw the item.
            //string text = item.ToString();
            var bmp = (Bitmap)item;
            //SizeF stringSize = e.Graphics.MeasureString(text, this.Font);
            e.Graphics.DrawImage(bmp, new PointF(0, 0));
            //e.Graphics.DrawString(text, this.Font, new SolidBrush(Color.White),
            //    new PointF(5, e.Bounds.Y + (e.Bounds.Height - stringSize.Height) / 2));
        }
    }

    public struct FilterSet
    {
        public DateTime FilterAfter;
        public DateTime FilterBefore;
        public int FilterPostMin;
        public int FilterPostMax;
        public string FilterName;
        public string FilterEmail;
        public string FilterSubject;
        public string FilterComment;
        public string FilterFilename;
        public string FilterMD5;
        public string FilterTripcode;
        public Board FilterBoard;
        public bool FilterRegex;

        public FilterSet(DateTime filterAfter, DateTime filterBefore,
            int filterPostMin, int filterPostMax, string filterName,
            string filterEmail, string filterSubject, string filterComment,
            string filterFilename, string filterMD5, string filterTripcode,
            Board filterBoard, bool filterRegex)
        {
            FilterAfter = filterAfter;
            FilterBefore = filterBefore;
            FilterPostMin = filterPostMin;
            FilterPostMax = filterPostMax;
            FilterName = filterName;
            FilterEmail = filterEmail;
            FilterSubject = filterSubject;
            FilterComment = filterComment;
            FilterFilename = filterFilename;
            FilterMD5 = filterMD5;
            FilterTripcode = filterTripcode;
            FilterBoard = filterBoard;
            FilterRegex = filterRegex;
        }
    }
    public enum Board { Both, Mlp, Co, };
}
